<?php

global $OK_proj;

require_once $OK_proj.'include/OAUC201R_utility.inc';

define ('FORMAT_DB', 'formatdb');
define ('FORMAT_VW', 'formatview');

interface DataField {
	public function read($array);
	public function response();
	public function getValue($format);
	public function validate(&$error);
	public function format($type);
}


class Field implements DataField {
	
	private $params;
	
	public function __construct($n, $l, $t, $req, $val='')  {
		$this->params['name'] = $n;
		$this->params['label'] = $l;
		$this->params['type'] = $t;
		$this->params['value'] = $val;
		$this->params['required'] = $req;
		$this->params['toupper'] = false;
		$this->params['formatfn'] = function ($type){return $this->params['value'];};
	}	
	
	function __call($name, $args) {
		
		$name = strtolower($name);
		
		if (count($args) == 0) {
			return nvli($this->params, $name, '');
		}
		
		$this->params[$name] = $args[0];
		
	}
	
	public function read($array) {
	    if ($this->params['toupper']) {
            $this->params['value'] = strtoupper(nvli($array, $this->params['name'], ''));
	    } else {
	        $this->params['value'] = nvli($array, $this->params['name'], '');
	    }
	}
	
	public function response() {
		return array($this->params['name'] => $this->params['value']);
	}
	
	public function getValue($format = FORMAT_DB) {
		return $this->params['value'];
	}
	
	public function validate(&$error) {
	    $type = $this->type();
	    $params = $GLOBALS['spiTypes'][$type];
	    $req =$this->required();
	    $label = $this->label();
	    
	    list($valid, $err) = OAUC201R_validate($this->value(), $params, $req);
	    if (!$valid) {
	        $error = $err;
	    }
	    return $valid;
	}
	
	public function formatfn($callable) {
	    $this->params['formatfn'] = $callable;
	}
	
	public function formatfn() {
	    return $this->params['formatfn'];
	}
	
	public function format($type = FORMAT_DB) {
	    return $this->params['formatfn']($type);
	}
	
}




class DataForm {
	
	public $fields;
	
	public function add($field) {
		$this->fields[$field->name()] = $field;
	}
	public function read($request){
		foreach ($this->fields as $field) {
			$field->read($request);
		}
	}
	public function validate(&$errs) {
	    $valid = true;
	    $errs = array();
	    foreach ($this->fields as $field) {
	        $valid &= $field->validate($errors);
	        if (!$valid) {
	            $errs = array_merge($errs, $errors);
	        }
	    }		
	    
	    return $valid;
	}
	
	public function getValues($format = FORMAT_DB) {
		$values = array();
		foreach($this->fields as $field) {
			if ($field instanceof FieldCollection) {
				$values = array_merge($values, $field->getValue($format));
			} else {
				$values = array_merge($values, array($field->name() => $field->getValue($format)));
			}
			
		}
		return $values;
	}
	
	public function response() {
		$response = array();
		foreach ($this->fields as $field) {
			$response = array_merge($response, $field->response());
		}
		return $response;
	}	
	
}

class FieldCollection implements DataField {
	/**
	 * 
	 * @var array of Field
	 */
	protected $field_array = array();
	protected  $_name_postfix;
	public $label;
	
	function __call($name, $args) {
	
	    $name = strtolower($name);
	
	    if (!isset($this->field_array[$name])) {
	        return;
	    }
	
	    if (count($args) == 0) {
	        return $this->field_array[$name]->value();
	    }
	
	    $this->field_array[$name]->value(strtoupper($args[0]));
	
	}
	
	public function read($array) {
		foreach ($this->field_array as $field) {
			$field->read($array);
		}
	}
	
	public function response() {
		$response = array();
		foreach ($this->field_array as $field) {
			$response = array_merge($response, $field->response());
		}
		return $response;
	}
	
	public function getValue($format = FORMAT_DB) {
		$values = array();
		foreach($this->field_array as $field) {
			$values = array_merge($values, array($field->name() => $field->getValue($format)));
		}
		return $values;
	}
	
	public function validate(&$errors) {
	    $valid = true;
	    $errors = array();
	    foreach($this->field_array as $field) {
	        $validField = $field->validate($error);
	        if (!$validField) {
	            $errors[$field->label()] = $error;
	        }
	        $valid &= $validField;
	    }
	    return $valid;
	     
	}
	
}

abstract class FieldComposite implements DataField {
	protected $field_array = array();
	
	public function response() {
		$response = array();
		foreach ($this->field_array as $field) {
			$response = array_merge($response, $field->response());
		}
		return $response;
	}	
	
	abstract public function getValue($format);
	abstract public function read($array);
	
	public function validate(&$errors) {
	    $valid = true;
	    $errors = array();
	    foreach($this->field_array as $field) {
	        $validField = $field->validate($error);
	        if (!$validField) {
	            $errors[$field->label()] = $error;
	        }
	        $valid &= $validField;
	    }
	    return $valid;
	     
	}	
}


class FieldDate extends FieldComposite {
	
	private $_name_postfix;
	private $_requested;
	public $label;
	
	public function __construct ($name_pf, $l, $req) {
		$this->_name_postfix = $name_pf;
		$this->_requested = $req;
		$this->label = $l;
		
		$this->field_array['gg'] = new Field('gg_'.$name_pf, 'Giorno', 'giorno', $req);
		$this->field_array['mm'] = new Field('mm_'.$name_pf, 'Mese', 'mese', $req);
		$this->field_array['aa'] = new Field('aa_'.$name_pf, 'Anno', 'anno', $req);
	}
	
	public function name() {
		return $this->_name_postfix;
	}
	
	public function getValue($format) {
		
		$g = $this->field_array['gg']->getValue($format);
		$m = $this->field_array['mm']->getValue($format);
		$a = $this->field_array['aa']->getValue($format);

		if (empty($g) || empty($m) || empty($a)) {
		    return '';
		}
		
		switch ($format) {
			case FORMAT_DB : {
				return $a.$m.$g;
			} break;
		
			case FORMAT_VW : {
				return $g.'/'.$m.'/'.$a;
			}
		}	

	}

	public function read($array) {
		$this->field_array['gg']->value(FieldDate::padZL($array, $this->field_array['gg']->name()));
		$this->field_array['mm']->value(FieldDate::padZL($array, $this->field_array['mm']->name()));
		$this->field_array['aa']->value(FieldDate::padZL($array, $this->field_array['aa']->name(),4));
	}
	
	private static function padZL($array, $index, $np = 2) {
		if (isset($array[$index]) && $array[$index] != '') {
			return str_pad($array[$index],$np, '0',STR_PAD_LEFT);
		}
	}
	
	public function validate(&$errors) {
	    $valids = parent::validate($errors);
	    if (!$valids) return false;
	    $data = $this->getValue(FORMAT_DB);
	    list($valid, $err) = OAUC201R_validateType($data, 'data', $this->_requested);
	    if (!$valid) {
	        $errors[$this->label] = $err;
	    }
	    return $valid;
	}
}

class FieldProtocollo extends FieldCollection {
	

	
	public function __construct ($name, $l, $req, $addpf = true) {
		
		$this->_name_postfix = '';
		$this->label = $l;
		
		if ($addpf) {
			$this->_name_postfix = '_'.$name;
		}
	
		$this->field_array['uo'] = new Field('prot_uo'.$this->_name_postfix, $name.' Unita Org.', 'provincia', $req);
		$this->field_array['uo']->toUpper(true);
		$this->field_array['num1'] = new Field('prot_num1'.$this->_name_postfix, $name.' Num. 1', 'prot_num1', $req);
		$this->field_array['num2'] = new Field('prot_num2'.$this->_name_postfix, $name.' Num. 2', 'prot_num2', $req);
		$this->field_array['anno'] = new Field('prot_anno'.$this->_name_postfix, $name.' Anno', 'anno', $req);
	}
	

	
	public function read($array) {
	    parent::read($array);
	    $this->field_array['anno']->value(FieldProtocollo::padZL($this->field_array['anno']->value()));
	    
	}
	
	private static function padZL($str, $np = 4) {
	   if (empty($str)) return;
	   return str_pad($str,$np, '0',STR_PAD_LEFT);
	}	
	
}


class FieldImmId extends FieldCollection {
    
    public function __construct ($name, $l, $req, $addpf = true) {
    
        $this->_name_postfix = '';
        $this->label = $l;
    
        if ($addpf) {
            $this->_name_postfix = '_'.$name;
        }
    
        $this->field_array['provincia']  = new Field('provincia'.$this->_name_postfix,   $name.' Provincia', 'provincia', $req);
        $this->field_array['diz_com']    = new Field('comune'.$this->_name_postfix,      $name.' Comune.', 'comune', $req);
        $this->field_array['cod_com']    = new Field('cod_com'.$this->_name_postfix,     $name.' Comune.', 'cod_com', $req);
        $this->field_array['tipo_cat']   = new Field('tipo_cat'.$this->_name_postfix,    $name.' Tipo Catasto', 'tipo_catasto', $req);
        $this->field_array['foglio']     = new Field('foglio'.$this->_name_postfix,      $name.' Foglio', 'foglio', $req);
        $this->field_array['part1']      = new Field('part1'.$this->_name_postfix,       $name.' Particella 1', 'particella1', $req);
        $this->field_array['part2']      = new Field('part2'.$this->_name_postfix,       $name.' Particella 2', 'particella2', false);
        $this->field_array['sub1']       = new Field('sub1'.$this->_name_postfix,        $name.' Subalterno 1', 'subalterno1', $req);
        $this->field_array['sub2']       = new Field('sub2'.$this->_name_postfix,        $name.' Subalterno 2', 'subalterno2', false);
    }    
    
    
}

